#include "myString.hpp"
#define BASE_SIZE (size_t)15
//MyString

MyString::MyString():
    counter((int*)new char[4 + BASE_SIZE + 1]()),
    start((char*)counter + 4),
    end_of_storage(start+BASE_SIZE), 
    finish(start)
{
    *counter = 1;
    std::cout<<"MyString()"<<std::endl;
}

MyString::MyString(size_t num, char c){
    size_t res = std::max(BASE_SIZE, num);
    counter = (int*) new char[4 + res + 1]();
    *counter = 1;
    start = (char*)counter + 4;
    end_of_storage = start + res;
    finish = start + num;
    memset(start, c, num);
    std::cout<<"MyString(size_t num, char c)"<<std::endl;
}
MyString::MyString(const char *str){
    size_t len = strlen(str);
    size_t res = std::max(BASE_SIZE, len);
    counter = (int*) new char[4 + res + 1]();
    *counter = 1;
    start = (char*)counter + 4;
    end_of_storage = start + res;
    finish = start + len;
    memcpy(start, str, len);
    std::cout<<"MyString(const char *str)"<<std::endl;

}

MyString::MyString(const MyString &rhs):
    counter(rhs.counter),
    start(rhs.start),
    end_of_storage(rhs.end_of_storage),
    finish(rhs.finish)
{
    ++(*counter);
    std::cout<<"MyString(const MyString &rhs)"<<std::endl;
}

MyString::~MyString(){
    --(*counter);
    std::cout<<*counter<<std::endl;
    if(*counter == 0){
        delete [] (char*)counter;
        counter = nullptr;
        start = nullptr;
        end_of_storage = nullptr;
        finish = nullptr;
        std::cout<<"~MyString"<<std::endl;
    }
}

MyString &MyString::operator=(const MyString &rhs){
    if(this != &rhs){
        if(--(*counter) == 0){
            delete [] (char*)counter;
        }
        counter = rhs.counter;
        start = rhs.start;
        end_of_storage = rhs.end_of_storage;
        finish = rhs.finish;
        ++(*counter);
    }
    std::cout<<"MyString operator=(const MyString &rhs)"<<std::endl;
    return *this;
}


MyString &MyString::operator=(const char *str){
    std::cout<<"MyString operator=(const char *str)-->>";
    MyString temp(str);
    *this = temp;
    return *this;
}

MyString::Instring &MyString::Instring::operator=(char c){
    if(c != (myString.start)[index]){
        if(myString.counts() > 1){
            myString.reserve(myString.capacity());
        }
        (myString.start)[index] = c;
    }

    return *this;
}

MyString operator+(const MyString &lhs, const char *str){
    return MyString(lhs).append(str);

}

MyString operator+(const MyString &lhs, const MyString &rhs){
    return MyString(lhs).append(rhs);
}

MyString operator+(const char *str, const MyString &rhs){
    return MyString(str).append(rhs);
}

MyString::Instring::operator char(){
    std::cout<<"operator char()"<<std::endl;
    return (myString.start)[index];
}

MyString::Instring MyString::operator[](const size_t index){
    return MyString::Instring(*this, index);
}

const char &MyString::operator[](std::size_t index) const{
    return *(start + index);
}

bool MyString::operator==(const char *str)const{
    if(strcmp(str, start) == 0){
        return true;
    }
    return false;
}

bool operator==(const char *str, const MyString &rhs){
    if(strcmp(str, rhs.start) == 0){
        return true;
    }
    return false;
}

bool MyString::operator==(const MyString &rhs)const{
    if(strcmp(rhs.start, start) == 0){
        return true;
    }
    return false;
}

bool operator!=(const MyString &rhs1, const MyString &rhs2){
    return !(rhs1 == rhs2);
}

bool MyString::operator>(const MyString &rhs){
    std::cout<<"bool MyString::operator>(const MyString &rhs)"<<std::endl;
    return (*this > rhs.start);
}
bool MyString::operator>(const char *str){
    std::cout<<"bool MyString::operator>(const char *str)"<<std::endl;
    return (strcmp(this->start, str) > 0);
}
bool operator>(const char* str, const MyString &rhs){
    std::cout<<"bool operator>(const char *str, const MyString &rhs)"<<std::endl;
    return (strcmp(str, rhs.start) > 0);
}

bool MyString::operator<(const MyString &rhs){
    std::cout<<"bool MyString::operator<(const MyString &rhs)"<<std::endl;
    return (*this < rhs.start);

}
bool MyString::operator<(const char *str){
    std::cout<<"bool MyString::operator<(const char *str)"<<std::endl;
    return (strcmp(start, str) < 0);

}
bool operator<(const char* str, const MyString &rhs){
    std::cout<<"bool operator<(const char *str, const MyString &rhs)"<<std::endl;
    return (strcmp(str, rhs.start) < 0);
}

bool operator<=(const MyString &rhs1, const MyString &rhs2){
    std::cout<<"bool operator<=(const MyString &rhs1, const MyString &rhs2)"<<std::endl;
    return (strcmp(rhs1.start, rhs2.start) <= 0);
}

bool operator>=(const MyString &rhs1, const MyString &rhs2){
    std::cout<<"bool operator<=(const MyString &rhs1, const MyString &rhs2)"<<std::endl;
    return (strcmp(rhs1.start, rhs2.start) <= 0);
}

std::ostream &operator<<(std::ostream & os, const MyString &rhs){
    return os<<(rhs.start);
}
std::ostream &operator<<(std::ostream &os, const MyString::Instring & ins){
    os<<(ins.myString.start)[ins.index];
    return os;
}

std::istream &operator>>(std::istream &is, MyString &rhs){
    char ch;
    while(is.get(ch) && isspace(ch));
    rhs.clear();

    do{
        rhs.push_back(ch);

    }while(is.get(ch) && !isspace(ch));


    if(isspace(ch))  is.putback(ch);
    return is;
}

MyString &MyString::append(const char *str){
    std::cout<<"append(const char *str)-->>";
    return append(MyString(str));
}

MyString &MyString::append(const MyString &rhs){
    size_t len = size() + rhs.size();
    size_t llen = size();
    size_t bigger = std::max(size(), rhs.size());
    bool need_create = 0;
    bool need_delete = 0;
    if(len > capacity()){
        need_create = 1;
        need_delete = 1;
    }
    if(*counter > 1){
        --(*counter);
        need_create = 1;
        need_delete = 0;
    }
    if(need_create){

        int *n_counter = (int*)new char[4 + 2*bigger + 1]();
        memcpy((char*)n_counter + 4, start, size());
        start = (char*)n_counter + 4;
        end_of_storage = start + 2*bigger;
        finish = start + len;
        if(need_delete){
            delete [] (char*)counter;
        }
        counter = n_counter;
        *counter = 1;
    }
    memcpy(start+llen, rhs.start, rhs.size());
    std::cout<<"append(const MyString &rhs)"<<std::endl;
    return *this;
}

MyString::Instring MyString::at(const size_t index){
    //TODO 越界检测
    return (*this)[index];
}

const char &MyString::at(const size_t index)const{
    //TODO 越界检测
    return (*this)[index];
}

void MyString::clear(){
    if(*counter > 1){
        --(*counter);
        size_t len = capacity();
        counter = (int*)new char[4 + len + 1]();
        *counter = 1;
        start = (char*)counter + 4;
        end_of_storage = start + len;
        finish = start;
    }else{
        memset(start, 0, size());
        finish = start;
    }
}

bool MyString::empty()const{
    return start == finish;
}

size_t MyString::size()const{
    return finish - start;
}

size_t MyString::capacity() const{
    return end_of_storage - start;
}

MyString &MyString::reserve(size_t num){
    size_t res = std::max(num, BASE_SIZE);
    int *n_counter = (int*)new char[4 + res + 1]();
    size_t len = size();
    memcpy((char*)n_counter + 4, start, len);
    start = (char*)n_counter + 4;
    end_of_storage = start + res;
    finish = start + len;
    if(--(*counter) == 0){
        delete [] (char*)counter;
    }
    counter = n_counter;
    *counter = 1;
    return *this;
}
void MyString::push_back(char ch){
    if(*counter > 1){
        reserve(capacity());
    }
    if(end_of_storage == finish){
        reserve(2 * size());
    }
    *finish = ch;
    ++finish;
}

const char * MyString::c_str() const{
    return start;
}

int MyString::counts()const{
    return *counter;
}









